package com.grad.why.studentsystem.controller;

import com.grad.why.studentsystem.domain.Camera;
import com.grad.why.studentsystem.domain.FaceImgPath;
import com.grad.why.studentsystem.domain.Optionparams;
import com.grad.why.studentsystem.domain.current.CurrentCourse;
import com.grad.why.studentsystem.domain.current.CurrentFaceImgPath;
import com.grad.why.studentsystem.service.CameraService;
import com.grad.why.studentsystem.service.FaceInfoService;
import com.grad.why.studentsystem.service.OptionparamsService;
import com.grad.why.studentsystem.service.StudentService;
import com.grad.why.studentsystem.util.Util;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/studentManageSystem")
public class FaceInfoController {
    @Autowired
    private FaceInfoService faceInfoService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private OptionparamsService optionparamsService;

    @Autowired
    private CameraService cameraService;

    @RequestMapping("/getStudentFaceInfos")
    @ResponseBody
    public Object getProjectInfos(
            @RequestParam(required = false, defaultValue = "0", value = "offset") int offset,
            @RequestParam(required = false, defaultValue = "10", value = "limit") int limit,
            @RequestParam(required = false, defaultValue = "", value = "search") String search
    ) {
        try {
            List<CurrentFaceImgPath> rows = faceInfoService.getFaceImgPath(offset, limit, search);
            long total = faceInfoService.getFaceImgPathLength(search);
            Map<String, Object> result = new HashMap<>(2);
            result.put("rows", rows);
            result.put("total", total);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping("/getStudentNameBySid")
    @ResponseBody
    public String getStudentNameBySid(String sid){
        try{
            if(isDigit(sid)){
                return studentService.getStudentNameBySid(Integer.parseInt(sid));
            }else{
                return null;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public boolean isDigit(String str){
        char[] character = str.toCharArray();
        for(char c : character){
            if(!Character.isDigit(c)){
                return false;
            }
        }
        return true;
    }

    @RequestMapping("/addFaceInfoByStudentId/{sid}")
    @ResponseBody
    public String addFaceInfoByStudentId(@RequestParam("file") MultipartFile file, @PathVariable("sid") String sid) {
        String fileName = file.getOriginalFilename();
        if(fileName.indexOf("\\") != -1){
            fileName = fileName.substring(fileName.lastIndexOf("\\"));
        }
        String rootPath = optionparamsService.getParamValueByParamName("imgRootPath");
        String filePath = rootPath+sid;
        File targetFile = new File(filePath);

        if(!targetFile.exists()){
            targetFile.mkdirs();
        }

        File[] files = targetFile.listFiles();
        int maxId = -1;
        for(int i = 0;i<files.length;i++){
            File f = files[i];
            String s = f.getName();
            s = s.split("\\.")[0];
            s = s.split("_")[1];
            if(Integer.parseInt(s)>maxId){
                maxId = Integer.parseInt(s);
            }
        }

        maxId = maxId + 1;
        FileOutputStream out = null;
        try {
            String rimg = "";
            if(fileName.contains(".jpg")){
                out = new FileOutputStream(filePath+"/"+sid+"_"+maxId+".jpg");
                rimg = "/Path/"+sid+"/"+sid+"_"+maxId+".jpg";
            }else if(fileName.contains(".jpge")){
                out = new FileOutputStream(filePath+"/"+sid+"_"+maxId+".jpge");
                rimg = "/Path/"+sid+"/"+sid+"_"+maxId+".jpge";
            }else if(fileName.contains(".png")){
                out = new FileOutputStream(filePath+"/"+sid+"_"+maxId+".png");
                rimg = "/Path/"+sid+"/"+sid+"_"+maxId+".png";
            }else if(fileName.contains(".JPG")){
                out = new FileOutputStream(filePath+"/"+sid+"_"+maxId+".jpg");
                rimg = "/Path/"+sid+"/"+sid+"_"+maxId+".jpg";
            }else if(fileName.contains(".JPGE")){
                out = new FileOutputStream(filePath+"/"+sid+"_"+maxId+".jpge");
                rimg = "/Path/"+sid+"/"+sid+"_"+maxId+".jpge";
            }else if(fileName.contains(".PNG")){
                out = new FileOutputStream(filePath+"/"+sid+"_"+maxId+".png");
                rimg = "/Path/"+sid+"/"+sid+"_"+maxId+".png";
            }

            if(rimg.equals("")){
                return null;
            }

            out.write(file.getBytes());
            out.flush();
            out.close();

            //需传入的参数
            String a = filePath+"/"+sid+"_"+maxId;
            if(fileName.contains(".jpg")){
                a = a + ".jpg";
            }else if(fileName.contains(".jpge")){
                a = a + ".jpge";
            }else if(fileName.contains(".png")){
                a = a + ".png";
            }else if(fileName.contains(".JPG")){
                a = a + ".jpg";
            }else if(fileName.contains(".JPGE")){
                a = a + ".jpge";
            }else if(fileName.contains(".PNG")){
                a = a + ".png";
            }
            Image srcImg = ImageIO.read(new FileInputStream(a));//取源图
            int width = 640; //假设要缩小到640点像素
            int height = srcImg.getHeight(null)*640/srcImg.getWidth(null);//按比例，将高度缩减
            Image smallImg =srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage bi1 = toBufferedImage(smallImg);
            //存到硬盘中
            ImageIO.write(bi1,a.split("\\.")[1], new File(a));
            //设置命令行传入参数

            String[] args = new String[] { "python", "D:\\git\\face_recognition-master\\face_recognition-master\\mytest\\testByImage.py", a};
            Process pr = Runtime.getRuntime().exec(args);
            BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
            String line;
            boolean flag = true;
            while ((line = in.readLine()) != null) {
                if(Integer.parseInt(line) > 0){
                     Integer maxDataId = faceInfoService.getMaxId() + 1;
                     FaceImgPath faceImgPath = new FaceImgPath();
                     faceImgPath.setFid(maxDataId);
                     faceImgPath.setPath(rimg);
                     faceImgPath.setSid(Integer.parseInt(sid));
                     int rows = faceInfoService.addFaceInfoBySidAndFacePath(faceImgPath);

                     //加入到人脸特征集
                     if(rows>0){
                         List<Camera> cameraList = cameraService.getRunningCameraInfos();
                         for(int i = 0;i<cameraList.size();i++){
                             Camera camera = cameraList.get(i);
                             camera.setShouldupdate(1);
                             cameraService.updateCameraInfo(camera);
                         }
                         in.close();
                         pr.waitFor();
                         return rimg;
                     }else{
                         flag = false;
                         break;
                     }
                }else{
                    flag = false;
                    if(fileName.contains(".jpg")){
                        File delFile = new File(filePath+"/"+sid+"_"+maxId+".jpg");
                        delFile.delete();
                    }else if(fileName.contains(".jpge")){
                        File delFile = new File(filePath+"/"+sid+"_"+maxId+".jpge");
                        delFile.delete();
                    }else if(fileName.contains(".png")){
                        File delFile = new File(filePath+"/"+sid+"_"+maxId+".png");
                        delFile.delete();
                    }else if(fileName.contains(".JPG")){
                        File delFile = new File(filePath+"/"+sid+"_"+maxId+".jpg");
                        delFile.delete();
                    }else if(fileName.contains(".JPGE")){
                        File delFile = new File(filePath+"/"+sid+"_"+maxId+".jpge");
                        delFile.delete();
                    }else if(fileName.contains(".PNG")){
                        File delFile = new File(filePath+"/"+sid+"_"+maxId+".png");
                        delFile.delete();
                    }
                    break;
                }
            }

            in.close();
            pr.waitFor();
            if(flag == true){
                List<Camera> cameraList = cameraService.getRunningCameraInfos();
                for(int i = 0;i<cameraList.size();i++){
                    Camera camera = cameraList.get(i);
                    camera.setShouldupdate(1);
                    cameraService.updateCameraInfo(camera);
                }
                return rimg;
            }else{
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping("/deleteFaceInfoByFid/{ids}")
    @ResponseBody
    public String deleteFaceInfoByFid(@PathVariable("ids") String ids){
        try{
            String[] fidArray = ids.split("-");
            for(String s : fidArray){
                int n = faceInfoService.deleteFaceInfoByFid(Integer.parseInt(s));
                if(n<=0){
                    return null;
                }
            }
            return "OK";
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping("/uploadFaceInfos")
    @ResponseBody
    public String uploadFaceInfos(@RequestParam("file") MultipartFile file){
        try{
            String fileUploadRootPath = optionparamsService.getParamValueByParamName("fileRootPath");
            String fileName = file.getOriginalFilename();
            String uploadCurrentFileName = fileUploadRootPath+"uploadFacesInfo/"+ new Date().getTime() + fileName;

            File fileRootPath = new File(fileUploadRootPath+"uploadFacesInfo");

            if(!fileRootPath.exists()){
                fileRootPath.mkdirs();
            }

            FileOutputStream out = new FileOutputStream(uploadCurrentFileName);
            out.write(file.getBytes());
            out.flush();
            out.close();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            DecimalFormat decimalFormat = new DecimalFormat("##0");//格式化设置
            InputStream is = new FileInputStream(uploadCurrentFileName);
            Workbook wb = null;

            if(uploadCurrentFileName.split("\\.")[1].equals("xls")){
                wb = new HSSFWorkbook(is);
            }else if(uploadCurrentFileName.split("\\.")[1].equals("xlsx")){
                wb = new XSSFWorkbook(is);
            }

            int sheetNumber = wb.getNumberOfSheets();
            int InsertCount = 0;
            Row title = wb.getSheetAt(0).getRow(0);
            if(!title.getCell(0).getStringCellValue().equals("人脸编号")||
                    !title.getCell(1).getStringCellValue().equals("学生编号")||
                    !title.getCell(2).getStringCellValue().equals("学生姓名")||
                    !title.getCell(3).getStringCellValue().equals("图片路径")){
                return "请下载模板进行";
            }

            for(int i = 0;i<sheetNumber;i++) {
                int index = 1;
                for(Row row : wb.getSheetAt(i)){
                    if(row == null){
                        continue;
                    }else{
                        if(index == 1){

                        }else{
                            if(row.getCell(0) == null){
                                index++;
                                continue;
                            }else{
                                FaceImgPath faceImgPath = new FaceImgPath();
                                faceImgPath.setFid((int)Double.parseDouble(Util.formGetCellType(row.getCell(0))));
                                faceImgPath.setSid((int)Double.parseDouble(Util.formGetCellType(row.getCell(1))));

                                String imgPath = Util.formGetCellType(row.getCell(3));
                                MultipartFile multipartFile = getMulFileByPath(imgPath);
                                String reulst = addFaceInfoByStudentId(multipartFile,String.valueOf((int)Double.parseDouble(Util.formGetCellType(row.getCell(1)))));
                                if(reulst != null){
                                    InsertCount++;
                                }else{
                                    index++;
                                    continue;
                                }
                            }
                        }
                        index++;
                    }
                }
            }

            if(InsertCount<=0){
                return "添加失败";
            }else{
                return "添加"+InsertCount+"条数据";
            }
            //上传学生信息逻辑
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private MultipartFile getMulFileByPath(String picPath) throws FileNotFoundException {
        FileItem fileItem = createFileItem(picPath);
        MultipartFile mfile = new CommonsMultipartFile(fileItem);
        return mfile;
    }

    private FileItem createFileItem(String filePath) throws FileNotFoundException {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "textField";
        int num = filePath.lastIndexOf(".");
        String extFile = filePath.substring(num);
        FileItem item = factory.createItem(textFieldName, "text/plain", true,
                "MyFileName" + extFile);
        File newfile = new File(filePath);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try
        {
            FileInputStream fis = new FileInputStream(newfile);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192))
                    != -1)
            {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return item;
    }


    public BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage)image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see e661 Determining If an Image Has Transparent Pixels
        //boolean hasAlpha = hasAlpha(image);

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
       /* if (hasAlpha) {
         transparency = Transparency.BITMASK;
         }*/

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            //int type = BufferedImage.TYPE_3BYTE_BGR;//by wang
        /*if (hasAlpha) {
         type = BufferedImage.TYPE_INT_ARGB;
         }*/
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }
}
